#include <QHostAddress>
#include <QSemaphore>
#include <QByteArray>
#include <QtGlobal>
#include "tinyalsa.h"
#include "alsa.h"
#include "alsa/asoundlib.h"
#include "dcuinformation.h"
#include "io.h"


QSemaphore audio_ready(0);
char audio_data[1024];
extern unsigned char gb_type;
void Alsa::run() //人工，对讲和乘客报警
{
    char audio_buffer[1024+20] = {0};
    extern char dcu_ID;
    extern unsigned char bjq_ID;
    extern unsigned char djbj_type;
    extern unsigned char dj_status;
    extern unsigned char bj_status;
    unsigned char cnt = 5;
    static int tag = 0;
    running = true;
    static bool init_once = false;
    int rate = 16000;//默认16k采样率
    set_status(ALSA_PLAY);
    qDebug() << "gb_type = " << gb_type;
//    if(StationInfo.EnableJianTing) //判断是否使能司机室监听
//    {
//        qDebug() << "jianting enabled";
//         pcm = pcm_dev_init();
//        if(pcm == NULL)
//            qDebug() << "pcm open error";

//        set_vol(90, 90);

//        alsa_recv->set_alsa_dev(pcm);
//        alsa_recv->set_status(ALSA_PLAY);
//        alsa_recv->start();
//    }

    //打开声卡输出设备
//    pcm = pcm_dev_init(16000);
//    if(pcm == NULL)
//        qDebug() << "pcm open error";

//    set_vol(90, 90);

//    alsa_recv->set_alsa_dev(pcm);
//    alsa_recv->set_status(ALSA_PLAY);
   // alsa_recv->start();

  //  receive();
  //  set_vol(90, 90);
//////////////////////
    if(gb_type != OCC && gb_type != MAN_OTHER)
    {

        audio_buffer[0] = 'd';
        audio_buffer[1] = 'c';
        audio_buffer[2] = 'u';
        if(djbj_type == RENGONG) //人工广播
        {
            audio_buffer[3] = 'r';
            audio_buffer[4] = 'g';
            audio_buffer[14] = SPEAKING;
        }
        else if(djbj_type == INTERPHONE) //司机对讲
        {
            audio_buffer[3] = 'd';
            audio_buffer[4] = 'j';
            audio_buffer[14] = dj_status;
        }
        else if(djbj_type == BAOJING) //乘客报警
        {
            audio_buffer[3] = 'b';
            audio_buffer[4] = 'j';
            audio_buffer[11] = bjq_ID;
            audio_buffer[14] = bj_status;
            rate = 16000;
        }

        audio_buffer[10] = dcu_ID;

        audio_send = new QUdpSocket(0);
        pcm_cap = pcm_cap_dev_init(rate);  //打开PCM read 设备
        if(pcm_cap == NULL)
            {
                qDebug() << "pcm capture open error";
            }

       //  receive();
//         pcm_cap_lock.acquire(1);
//         pcm_cap = pcm_cap_dev_init(rate);
//         pcm_cap_lock.release(1);
//         if(pcm_cap == NULL)
//         qDebug() << "pcm capture open error";
//           qDebug("bj_status = %d",bj_status);

        while(status == ALSA_PLAY)
        {

           // qDebug("status = %d",status);
            if(djbj_type == RENGONG || dj_status == SPEAKING || bj_status == HH_SPEAKING)
            {

                pcm_dev_read(pcm_cap, &audio_buffer[20], 1024);
            }


            if(djbj_type == RENGONG) //人工广播
            {
                audio_send->writeDatagram(&audio_buffer[20], 1024, QHostAddress("230.10.10.23"), 20060); //Todo:发送多次以保证数据被接受  广播数据发送
            }
            else if(djbj_type == INTERPHONE) //司机对讲
            {
                audio_send->writeDatagram(&audio_buffer[20], 1024, QHostAddress("230.10.10.25"), 20060); //Todo:发送多次以保证数据被接受  广播数据发送
                 audio_send->writeDatagram(&audio_buffer[20], 1024, QHostAddress("230.10.10.24"), 20060); //Todo:发送多次以保证数据被接受  广播数据发送
            }
            else if(djbj_type == BAOJING) //乘客报警
            {

                audio_send->writeDatagram(&audio_buffer[20], 1024, QHostAddress("230.10.10.26"), 20060); //Todo:发送多次以保证数据被接受 广播数据发送
            }
        }
        bj_status = dj_status = HH_HANG;
        pcm_cap_lock.acquire(1);
        if(pcm_cap)
        {
            pcm_cap_dev_close(pcm_cap);
            pcm_cap = NULL;
        }
        pcm_cap_lock.release(1);

        if(audio_send)
        {
            delete audio_send;
            audio_send = NULL;
        }

        bjq_ID = 0;

        init_once = false;
    }

    qDebug() << "alsa send stop " << ++tag;
    running = false;
}

void Alsa::receive()
{
    qDebug() << "jianting enabled";
    alsa_recv->set_status(ALSA_PLAY);
    int rate = 16000;
    extern unsigned char djbj_type;
    if(djbj_type == BAOJING)
        rate = 8000;

    pcm_lock.acquire(1);
    pcm = pcm_dev_init(rate);
    pcm_lock.release(1);
    if(pcm == NULL)
        qDebug() << "pcm open error";

    if(gb_type == SJDJ || gb_type == CKBJ)
        set_vol(75+5*StationInfo.DJJTVolume, 75+5*StationInfo.DJJTVolume);
    else
        set_vol(75+5*StationInfo.GBJTVolume, 75+5*StationInfo.GBJTVolume);

    alsa_recv->set_alsa_dev(pcm);
    alsa_recv->start();
}

void Alsa::change_status()
{
    if(status == ALSA_PLAY)
        status = ALSA_STOP;
    else
        status = ALSA_PLAY;
}

unsigned char Alsa::get_status()
{
    return status;
}

unsigned char Alsa::get_recv_status()
{
    return alsa_recv->get_status();
}

bool Alsa::is_running()
{
    return (running || alsa_recv->is_running());
//    return this->isRunning() | alsa_recv->isRunning();
}

void Alsa::set_status(unsigned char status)
{
    this->status = status;
}

void Alsa::stop()
{
    capture_close();
    //set_status(ALSA_STOP);

    //Alsa.set_status(ALSA_STOP);

    if(status == ALSA_PLAY)
    {
        change_status();
    }
    while(this->isRunning());

    if(pcm)
        pcm_cap_dev_close(pcm);
//    if(audio_send)
//    {
//        delete audio_send;
//        audio_send = NULL;
//    }
    if(alsa_recv->isRunning())
    {
        alsa_recv->stop();
    }
}

void Alsa::capture()
{

}

void AlsaRecv::run()
{
    int pcm_res = -1;
    const int buffer_size = 1024;
    char buffer[buffer_size] = {0};
    int count = 0;
    int res = 0;
    running = true;

    audio_pipe_fd = open(FIFONAME, O_RDONLY);
    if(audio_pipe_fd == -1)
    {
        qDebug() << "audio read open fifo fail";
        return;
    }

    while(status == ALSA_PLAY)
    {

        res = read(audio_pipe_fd, &buffer[count], 1024);
        if(res == -1)
            break;
        count += res;
        if(count >= buffer_size)
        {
            count = count > buffer_size? buffer_size : count;
            if(StationInfo.EnableJianTing)
                pcm_res = pcm_dev_write(pcm, buffer, count);
            count = 0;
        }
    }

    if(count > 0)
    {
        count = count > buffer_size? buffer_size : count;
        pcm_res = pcm_dev_write(pcm, buffer, count);
        count = 0;
    }

//    if(audio_ready.available())
//        audio_ready.release(1);

    if(audio_pipe_fd != -1)
    {
        ::close(audio_pipe_fd);
        audio_pipe_fd = -1;
    }

    pcm_lock.acquire(1);
    if(pcm)
    {
        pcm_dev_close(pcm);
        pcm = NULL;
    }
    pcm_lock.release(1);
    memset(audio_data, 0, 1024);
    qDebug() << "recv stop";
    running = false;
}

void AlsaRecv::audio_data_received()
{
    qDebug() << "audio_data_received";

    static long int bytes_write = 0;
    int  datasize = 0;
    char  buffer[1024*2];
    int res = 0;
    static int life_time = -1;

    datasize = audio_recv->pendingDatagramSize();
    audio_recv->readDatagram(buffer, datasize);
}

void AlsaRecv::stop()
{
//    if(audio_recv)
//    {
//        audio_recv->disconnect();
//        delete audio_recv;
//        audio_recv = NULL;
//    }
    set_status(ALSA_STOP);
//    audio_ready.release(1);
    qDebug() << "recv stopping...";
}

void AlsaRecv::set_status(unsigned char status)
{
    this->status = status;
}

bool AlsaRecv::is_running()
{
    return running;
}

void AlsaRecv::set_alsa_dev(struct pcm* pcm)
{
    this->pcm = pcm;
}

unsigned char AlsaRecv::get_status()
{
    return this->status;
}

void AlsaSim::run()
{
    int rate = 16000;
    const int buffer_size = 4096;
    char buffer[buffer_size];
    int count = 0;

    set_status(ALSA_PLAY);

    pcm_lock.acquire(1);
    pcm = pcm_dev_init(rate);
    if(pcm == NULL)
        qDebug() << "pcm playback open error";

    pcm_cap = pcm_cap_dev_init(rate);
    if(pcm_cap == NULL)
        qDebug() << "pcm capture open error";
    pcm_lock.release(1);

  //  relay_on();

    set_vol(75+5*StationInfo.GBJTVolume, 75+5*StationInfo.GBJTVolume);

    while(status == ALSA_PLAY)
    {
        pcm_dev_read(pcm_cap, &buffer[count], 1024);
        count += 1024;
        if(count >= buffer_size)
        {
            count = count > buffer_size? buffer_size : count;
            if(StationInfo.EnableJianTing)
                pcm_dev_write(pcm, buffer, buffer_size);
            count = 0;
        }
    }

    relay_off();

    if(pcm_cap)
    {
        pcm_cap_dev_close(pcm_cap);
        pcm_cap = NULL;
    }
    if(pcm)
    {
        pcm_dev_close(pcm);
        pcm = NULL;
    }

    qDebug() << "rg sim stop";
}

void AlsaSim::stop()
{
    capture_close();
    relay_off();
    set_status(ALSA_STOP);
    qDebug() << "rg sim stopping...";

}

void AlsaSim::set_status(unsigned char status)
{
    this->status = status;
}
